perm filename TELNET.FAI[TNX,MRC]1 blob
sn#301704 filedate 1977-08-22 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00069 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00006 00002 <MRC>TELNET.FAI3 06-AUG-77 09:13:24 TECO'd by MRC
C00013 00003 TITLE TELNET (USER)
C00015 00004 SET VARPC,100000 Where to store variables
C00017 00005 Program starts here
C00019 00006 SUB P,[XWD 2,2]
C00022 00007 Main command loop
C00024 00008 drops in
C00026 00009 Abnormal interrupts come here
C00028 00010 ESCINV: MOVEI A,101
C00030 00011 Get a character
C00033 00012 UCS1: SKIPG A,UCASC
C00035 00013 .NOUT: NOUT
C00036 00014 Uuo handler
C00037 00015 Map fork one to one with this fork through page 177
C00039 00016 Macro for generating commands
C00042 00017 YNT: CC(<signal.waiting.output>,<MOVEM NOA,SWOFLG>)
C00044 00018 Command table for echo modes
C00047 00019 Connection name table
C00049 00020 Symbol evaluator
C00051 00021 DELCH: CAMN PTR,BPTR Delete character, any to delete?
C00052 00022 End of symbol, try lookup
C00054 00023 PRQUES: PUSHJ P,ECHOIT
C00056 00024 Lookup symbol
C00059 00025 SYMCMP: CAIN B,"*" Asterisk
C00061 00026 SYMCLS: ILDB B,Y Get class indicator
C00062 00027 SYMNCL: PUSHJ P,SYMCLS
C00063 00028 News
C00065 00029 CONN2: HRROI A,[ASCIZ /is /]
C00066 00030 CONN3: PUSHJ P,INIFRK
C00068 00031 CONFL1:CONFL0: HRROI A,[ASCIZ /,
C00069 00032 Perform icp
C00070 00033 ICPA: MOVE B,-2(P) Get beginning of string
C00072 00034 ICPB: MOVE B,0(P) Beginning of string
C00074 00035 ICPFL2: SUB P,[XWD 2,2]
C00075 00036 OPNWAT: PUSH P,A
C00077 00037 Disconnect
C00079 00038 Set name for connection
C00081 00039 List connections
C00082 00040 Set mode switches
C00083 00041 WRTMDF: MOVE TAB,HOSTAB
C00085 00042 OPNMDF: MOVEI A,400000
C00086 00043 Status.of
C00087 00044 Exec
C00088 00045 Netstatus
C00090 00046 Set escape character
C00092 00047 Set terminal modes
C00094 00048 Echo.mode.is
C00096 00049 Set control character echoing
C00097 00050 Print current modes
C00099 00051 PCMDTB: XWD RAISEF,[ASCIZ /Raise/]
C00102 00052 TYPAL: PUSHJ P,.PBIN
C00103 00053 Typescript to a file
C00105 00054 Get uniform time in secs
C00107 00055 Divert output to a file
C00108 00056 Print where we are
C00110 00057 drops in
C00112 00058 Quit, exit back to exec
C00114 00059 Set remote mode
C00115 00060 Other routines
C00117 00061 SEND: CIS
C00120 00062 SEND3: SKIPN LNBFF(CNX) If not line buffering
C00121 00063 SFTDWN: AOSE LCASCF
C00123 00064 SNDLBF: CAIE A,"A"-100
C00124 00065 RECV: CIS
C00127 00066 RECVS: MOVNI A,SAVBFS Prepare wrapped pointer
C00129 00067 RECVFL: MOVEM B,D
C00131 00068 RCVCTL: CAIN B,TELASC
C00133 00069 RCVINS: PUSH P,A
C00135 ENDMK
C⊗;
;<MRC>TELNET.FAI;3 06-AUG-77 09:13:24 TECO'd by MRC
; Updated to correspond to latest BBN version
;<CCA-NETWORK>TELNET.FAI;5 19-DEC-74 02:06:55 EDIT BY HGM
;<CCA-NETWORK>TELNET.FAI;4 29-SEP-74 11:10:42 EDIT BY HGM
; Adding a bit of fork setup PMAPs so can debug ↑C↑C glitch
;<CCA-NETWORK>TELNET.FAI;3 12-JUL-73 00:05:30 EDIT BY HGM
;<CCA-NETWORK>TELNET.FAI;2 23-JUN-73 08:08:56 EDIT BY HGM
;<CCA-NETWORK>TELNET.FAI;1 7-FEB-73 19:22:17 EDIT BY HGM
; Recovering <DOCUMENTATION>
;<SOURCES>TELNET.FAI;28 18-JAN-73 11:20:44 EDIT BY TOMLINSON
;<SOURCES>TELNET.FAI;27 17-JAN-73 16:46:23 EDIT BY TOMLINSON
;<SOURCES>TELNET.FAI;26 16-JAN-73 10:52:09 EDIT BY TOMLINSON
; Deleted surveying and time constant. Revamped receive fork.
;<TOMLINSON>TELNET.FAI;13 15-JAN-73 14:02:33 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;12 15-JAN-73 13:43:16 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;11 15-JAN-73 13:13:11 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;10 15-JAN-73 12:29:13 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;9 15-JAN-73 11:57:40 EDIT BY TOMLINSON
;<TOMLINSON>MESSAGE.TXT;2 14-JAN-73 17:10:46 EDIT BY TOMLINSON
; ↑↑↑ Looks like he glitched on this one!! - MRC
;<TOMLINSON>TELNET.FAI;6 14-JAN-73 16:51:00 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;5 14-JAN-73 13:50:18 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;4 14-JAN-73 13:20:44 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;3 11-JAN-73 14:12:15 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;2 11-JAN-73 13:32:49 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;1 11-JAN-73 12:36:52 EDIT BY TOMLINSON
;<SOURCES>TELNET.FAI;25 10-SEP-72 10:07:17 EDIT BY TOMLINSON
;<SOURCES>TELNET.FAI;24 8-SEP-72 10:02:57 EDIT BY TOMLINSON
;<SOURCES>TELNET.FAI;23 8-SEP-72 9:08:11 EDIT BY TOMLINSON
;<SOURCES>TELNET.FAI;22 5-SEP-72 11:37:29 EDIT BY TOMLINSON
;<SOURCES>TELNET.FAI;21 5-SEP-72 11:33:24 EDIT BY TOMLINSON
;<SOURCES>TELNET.FAI;20 5-SEP-72 11:17:41 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;46 3-SEP-72 11:37:58 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;45 2-SEP-72 16:02:59 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;44 2-SEP-72 15:56:36 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;43 2-SEP-72 15:54:09 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;42 2-SEP-72 15:28:21 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;41 2-SEP-72 15:13:34 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;40 2-SEP-72 14:54:29 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;39 2-SEP-72 14:45:07 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;38 2-SEP-72 14:43:04 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;37 2-SEP-72 14:19:33 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;36 2-SEP-72 13:59:08 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;35 2-SEP-72 13:57:07 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;34 2-SEP-72 12:04:40 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;33 2-SEP-72 11:33:29 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;32 28-JUL-72 15:15:14 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;31 28-JUL-72 14:24:37 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;30 28-JUL-72 14:17:41 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;29 28-JUL-72 13:27:03 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;28 28-JUL-72 11:42:16 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;27 28-JUL-72 11:23:30 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;26 28-JUL-72 11:09:29 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;25 28-JUL-72 10:53:32 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;24 28-JUL-72 10:29:02 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;23 27-JUL-72 16:59:25 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;22 27-JUL-72 16:01:50 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;21 27-JUL-72 15:55:01 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;20 3-JUL-72 13:29:08 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;19 3-JUL-72 13:22:25 EDIT BY TOMLINSON
;<TOMLINSON>TELNET.FAI;10 29-JUN-72 21:15:41 EDIT BY TOMLINSON
TITLE TELNET (USER)
SUBTTL R.S.Tomlinson
VERNUM: ASCIZ \4.0 August 6, 1977\]
BLOCK 3
OPDEF ERROR [1B8]
; Accumulators
A←1
B←2
C←3
D←4
X←5
Y←6
Z←7
PTR←10
TAB←11
NOA←12
CNX←13
NCNX←14
P←17
F←0
; Flags (rh of f)
REMOTF←←1 ; Operating in remote mode
COMMDF←←4 ; In command mode
NSTIWF←←2 ; Don't do STIW's
TMPF←←400000 ; Temporary flags
TMPF2←←200000
; Parameters
NPDL←←2000 ; Size of push list
NCONN←←7 ; Number of connections to remember
NHSTW←←(=256+=35)/=36 ; Number of words in host bit tables
IESC←←"Z"-100 ; Initial escape character
ICBF←←"O"-100 ; Initial clear output buffer character
TELSNC←←200 ; Sync sequence to serving site
TELBRK←←201 ; Break character
TELNOP←←202 ; Telnet nop character
TELNEC←←203 ; Don't echo
TELECH←←204 ; Do echo
TELHID←←205 ; Hide input
TELASC←←240 ; Use ASCII
ESCCHN←←0 ; Use channel 0 for escape
ABNCHN←←2 ; Channel 2 for abnormal connection termination
NTICHN←←3 ; Channel 3 for network PSI's
CBFCHN←←4
SAVBFS←←4000 ; Size of string saving buffer
SET VARPC,100000 ; Where to store variables
; Variables etc.
ARRAY HOSTRG[4*=256]
ARRAY SHOSTB,NHOSTB[=256]
INTEGER SHSTAB,NHSTAB,CONTAB
ARRAY PDL[NPDL]
ARRAY COMBUF[200]
ARRAY BIGBUF[4000]
INTEGER LODFLG,WATFLG,TCASE,TRMLWC
INTEGER BPTR,LPTR,SVP
INTEGER TTCOC0,TTCOC1,TTMOD0,TTMODR,TTMODC,JOBTIW,HDX,NFANCY
INTEGER ESCAPE,ESCCOD,CBFCHR,CBFCOD,LSTBDI,CONCSF
INTEGER ABNLCK,ABNCNX
INTEGER LCASCF,UCASCF
INTEGER LCASC,LCASL,UCASC,UCASL,UNSFT
INTEGER BRKC,SYNC,QUOT,QUOTF
ARRAY FAC[20]
INTEGER IJFN,JJFN,AJFN,SCRJFN,SCRCNT,SCRTIM
INTEGER DIVJFN,DIVSWT,RLACJ,SPCFRK
INTEGER SKTMSK,FSKT,FHST,FHSTN,RETPC1,RETPC2,RETPC3
ARRAY SNDJFN,RCVJFN,SNDFRK,RCVFRK,LSKT,ELCLF,LFCRF,LNBFF[NCONN+1]
ARRAY XPARNT,CBFCNT[NCONN+1]
ARRAY RAISEF,LOWERF,ECHCOC,CONTB,SAVINP,SAVINC,SAVONP,SAVSWT[NCONN+1]
ARRAY CONNAM[3+3*NCONN]
INTEGER ICPTIM,SUMTOT,SUMPHC,SUMSCL,SUMTIM,SUMTM2,SUMFST,SUMSRT,SWOFLG
ARRAY SUMAVG,SUMAVC,SUMUPT,SUMUPC,SUMTTC[400]
INTEGER TERM
INTEGER JUNK
INTEGER NTICNT,NTIIA,CLROBF
ARRAY LINBUF[200]
SET FRKPC,200000
USE FRKPC
SPDL: BLOCK 100
FKRET1: BLOCK 1
FKRET2: BLOCK 1
FKRET3: BLOCK 1
SAVBUF: BLOCK SAVBFS
USE
; Program starts here
START: HRROI A,[ASCIZ /
User Telnet /]
PSOUT
HRROI A,VERNUM
PSOUT
HRROI A,[ASCIZ /. Type HELP<cr> for help./]
PSOUT
RSTART: RESET ; Reset the world
MOVE P,[XWD -NPDL,PDL-1]
MOVE A,[PUSHJ P,UUO]
MOVEM A,41
MOVEI A,400000
RPCAP ; Find out what we can do
AND B,[1B0!1B2]
IOR C,B
EPCAP ; Enable control-C stealing
TLNE C,(1B0)
TROA F,NSTIWF
TRZ F,NSTIWF
SETZB F,VARS
MOVE A,[XWD VARS,VARS+1]
BLT A,EVARS-1 ; Zero all variables
MOVE A,[SIXBIT /HOSTN/]
SYSGT
PUSH P,B
MOVE A,[SIXBIT /HSTNAM/]
SYSGT
PUSH P,B
MOVEI Y,NHOSTB-1
MOVEI X,SHOSTB-1
MOVEI C,HOSTRG-1
HLLZ D,-1(P)
GTHSTL: HRRZ A,-1(P)
HRL A,D
GETAB
JRST 4,.-1
MOVEI B,1(C)
HRLI B,(<POINT 7,0>)
TLNN A,(1B0)
JRST [ PUSH Y,B
JRST .+2]
PUSH X,B
MOVE B,A
GTHSTE: HRRZ A,0(P) ; Hostab number
HRL A,B ; Offset
GETAB
JRST 4,.-1
PUSH C,A ; Store in hostrg
TRNE A,377 ; Done when reach null byte
AOJA B,GTHSTE ; Loop
LDB A,[POINT 9,B,17]
PUSH C,[PUSHJ P,.CVHST]
PUSH C,A
GTHSTN: AOBJN D,GTHSTL
HLLZS X
HLLZS Y
MOVNS X
MOVNS Y
HRRI X,SHOSTB
HRRI Y,NHOSTB
MOVEM X,SHSTAB
MOVEM Y,NHSTAB
SUB P,[XWD 2,2]
SETOM ABNLCK ; Unlock abnormal interrupt handler.
FOR VAR IN (UCASC,UCASL,LCASC,LCASL,UNSFT,QUOT,BRKC,SYNC)
< SETOM VAR
>
MOVSI B,-NCONN
ICNVL: MOVE A,[BYTE (1)0,0,0,0,0,0,0,1,0,1,1,0,0,1]
MOVEM A,ECHCOC(B) ; Initial control character local echo
SETOM LFCRF(B)
SETOM ELCLF(B)
AOBJN B,ICNVL
MOVEI A,CONTB
MOVEM A,CONTAB ; CONTAB points at CONTB
SETZ NOA,
PUSHJ P,SETSCR ; Set up for typescript
MOVEI A,IESC ; Setup initial escape character
MOVEM A,ESCAPE
PUSHJ P,CVINTC ; Convert character to interrup channel
JRST 4,. ; Can't fail
MOVEM A,ESCCOD
MOVEI A,ICBF
MOVEM A,CBFCHR
PUSHJ P,CVINTC
JRST 4,.
MOVEM A,CBFCOD
MOVEI A,400000
CIS
MOVE B,[XWD LEVTAB,CHNTAB]
SIR
EIR
MOVEI A,100
RFMOD ; Find out what kind of line we have
MOVEM B,TTMOD0 ; Remember same
TRNE B,1B32 ; Hdx terminal?
SETOM HDX ; Yes, set HDX flag
TLNE B,(1B3)
SETOM TRMLWC ; Remember term has lower case
ANDCMI B,77B23!3B25!17B29!1B30!1B31
PUSH P,B
IORI B,17B23!0B25!1B29
MOVEM B,TTMODC ; In command mode: break-all, echo-none
POP P,B
IORI B,17B23!1B29
MOVEM B,TTMODR ; No change for remote mode
RFCOC ; Get standard control output control
MOVEM B,TTCOC0
MOVEM C,TTCOC1
MOVEI A,ESCCHN ; PSI channel
HRL A,ESCCOD ; Escape terminal code
ATI
MOVEI A,CBFCHN
HRL A,CBFCOD
ATI ; Assign
MOVE B,[1⊗<43-ESCCHN>!1⊗<43-ABNCHN>!1⊗<43-NTICHN>!1⊗<43-CBFCHN>!1B9!1B11!1B15!7B18]
MOVEI A,400000
AIC ; Activate interrupt channel
; Main command loop
COMLP: TRO F,COMMDF
MOVEI A,101
DOBE
MOVE P,[XWD -NPDL,PDL-1]
MOVE NCNX,CNX
SETO B,
MOVEI A,-5
TRNN F,NSTIWF
STIW ; Restore terminal interrupt word
MOVEI A,100
MOVE B,TTMODC
SKIPE NFANCY
JRST [ TRZ B,77B23
TRO B,2B25!16B23
JRST .+1]
SFMOD ; Set tty mode for command input
MOVE B,[BYTE (2)0,0,1,1,1,1,1,2,0,2,2,1,2,2,1,1,1,1]
MOVE C,[BYTE (2)0,1,1,1,1,1,0,1,1,0,1,1,1,2]
SFCOC
HRROI A,[ASCIZ /
#/]
PUSHJ P,.PSOUT ; Prompt character
MOVE PTR,[POINT 7,COMBUF-1,34]
MOVEM PTR,LPTR ; Pointer to beginning of line
MOVEI A," "
IDPB A,PTR ; Deposit initial space to line up
MOVE TAB,COMTAB ; Setup to use COMTAB
PUSHJ P,SYMVAL ; Call symbol evaluator
SKIPE SNDJFN(CNX)
TRNN F,REMOTF ; Remote mode?
JRST COMLP ; No. stay in command mode
TRZ F,COMMDF
MOVEI A,"#"
PUSHJ P,.PBOUT
MOVEI A,37
PUSHJ P,.PBOUT
MOVEI A,-5
MOVN C,ESCCOD
MOVSI B,400000
ROT B,(C) ; Get bit for escape code
PUSH P,B
MOVN C,CBFCOD
MOVSI B,400000
ROT B,0(C)
IORM B,0(P)
POP P,B
IORI B,1B30 ; Include carrier off
TRNN F,NSTIWF
STIW ; And set TIW to that
; falls through
; drops in
MOVEI A,100
MOVE B,TTMODR
SKIPE XPARNT(CNX)
TRZ B,3B29
SFMOD ; Set TTY mode for remote
MOVE A,RCVFRK(CNX)
FFORK ; Freeze it
MOVEI A,400000
DIR ; Interrupts off to avoid confusion
SETZM SAVSWT(CNX) ; Resume output
MOVE A,RCVFRK(CNX)
RFSTS ; Get PC of receive fork
MOVE A,RCVFRK(CNX)
HRRZS B
CAILE B,RECV0 ; If fork will get back to RECV0
CAILE B,RECVB+1
JRST REST2 ; Skip the following
MOVEI B,RECV0
SFORK ; Restart fork
REST2: MOVEI A,400000
EIR
MOVE A,RCVFRK(CNX)
RFORK ; And resume
MOVE A,SNDFRK(CNX)
RFORK ; Resume send fork
WFORK ; Should wait forever
HRROI A,[ASCIZ /
Funny fork termination. Restarted./]
PUSHJ P,.PSOUT
JRST RSTART
; Abnormal interrupts come here
BADINT: MOVEI A,101
DOBE
TIME
SUBI A,=15000
CAMGE A,LSTBDI ; Within 5 seconds of last bad int?
JRST BADBAD ; Very bad
HRROI A,[ASCIZ /
Abnormal interrupt from location /]
PUSHJ P,.PSOUT
HRRZ B,RETPC1
MOVEI C,10
MOVEI A,101
PUSHJ P,.NOUT
JFCL
HRROI A,[ASCIZ /.
/]
PUSHJ P,.PSOUT
TIME
MOVEM A,LSTBDI
JRST ESCINZ
BADBAD: HALTF
JRST BADINT
; If remote host initiates disconnect, rec'v fork inits int'rpt to here
ABNINT: MOVE X,ABNCNX ; Get the correct context
PUSHJ P,DISC1
JRST ESCINZ
; Clear outbuf int comes here
CBFINT: SKIPE SNDJFN(CNX)
AOSE QUOTF
JRST CBFINZ
PUSH P,B
MOVEI B,SENDO
JRST SPCSND
CBFINZ: SETOM CLROBF
PUSH P,A
MOVEI A,101
CFOBF
POP P,A
DEBRK
DEBRK
; Escape interrupt comes to here
ESCINT: SKIPE SNDJFN ; If connection exists,
AOSE QUOTF ; And quote prefix typed,
JRST ESCINV
PUSH P,B
MOVEI B,SENDE
SPCSND: PUSH P,A ; Then sent escape character
MOVE A,SNDFRK(CNX)
FFORK
SFORK
RFORK
POP P,A
POP P,B
DEBRK
ESCINV: MOVEI A,101
TRNE COMMDF ; Command mode?
CFOBF ; Yes, flush output
ESCINZ: MOVEI A,100
CFIBF
SKIPE RLACJ ; Is there likely to be a JFN in ac 1?
TDNE A,[XWD -1,700000]
SKIPA ; Apparently not
PUSHJ P,CLRJFN ; Apparently yes
SETZM RLACJ
SKIPE A,SNDFRK(CNX) ; If there is a send fork
FFORK ; Freeze it
SKIPN RCVJFN(CNX) ; Connected?
JRST ESCINW ; No, skip this
SETOM SAVSWT(CNX) ; Switch to saving input
MOVE A,RCVFRK(CNX)
RFORK ; Leave running
ESCINW: SKIPE A,SPCFRK ; If there is a special fork
KFORK ; Kill it
SETZM SPCFRK
FOR JFN IN (AJFN,JJFN,IJFN),<
SKIPE A,JFN
PUSHJ P,CLRJFN
SETZM JFN> ; Release temporary JFN's
ESCI1: MOVE A,[XWD 10000,COMLP]
MOVEM A,RETPC1
DEBRK ; DEBRK back to COMLP
LEVTAB: RETPC1
RETPC2
RETPC3
CHNTAB: REPEAT ESCCHN,<XWD 1,BADINT>
XWD 1,ESCINT
0
XWD 1,ABNINT
XWD 3,NTIINT
XWD 2,CBFINT
REPEAT <=36-5-ESCCHN>,<XWD 1,BADINT>
FKLVT: FKRET1
FKRET2
FKRET3
FKCHT: 0
XWD 3,RCVINS
REPEAT =8,<0>
XWD 2,RCVEOF
XWD 1,IOERR
REPEAT =36-=12,<0>
; Get a character
GCH: PUSHJ P,.PBIN
CAIE A,177
CPOPJ: POPJ P,
HRROI A,[ASCIZ /XXX/]
PUSHJ P,.PSOUT
JRST COMLP
; Echo character in a
ECHOIT: SKIPE HDX
PUSHJ P,PBOUT0
SKIPE HDX
POPJ P,
SKIPE NFANCY
TRNN F,COMMDF
PUSHJ P,.PBOUT
POPJ P,
; Primary output with case indicate
.PEOUT: PUSHJ P,PBOUT0
CAIL A,100 ; Does character have case?
SKIPE TRMLWC ; Or does terminal have lower case?
JRST EOUTX1 ; Caseless
SKIPGE LCASL
SKIPL LCASC
SKIPA
JRST EOUTX1 ; Don't indicate if shift chars absent
SKIPGE UCASL
SKIPL UCASC
SKIPA
JRST EOUTX1
CAIE A,177
CAIN A,137
JRST EOUTX1
PUSH P,B
MOVE B,A
ANDI B,40 ; Extract case
ANDCMI A,40 ; Force upper
CAMN B,TCASE ; Same as current case?
JRST EOUTX0 ; No need to indicate
PUSH P,A
JUMPE B,IUPC ; Upper case
SKIPG A,LCASL ; Do we have a lower case lock?
JRST LCS1 ; No, try for lowercase char
PBOUT ; Yes, print it
MOVEM B,TCASE ; And remember new case
JRST EOUTX
LCS1: SKIPG A,LCASC ; Have we a lower case char prefix?
JRST EOUTX ; No, can't indicate
PBOUT ; Yes, print it
JRST EOUTX ; But don't change case
IUPC: SKIPG A,UCASL ; Do we have a upper case lock
JRST UCS1
PBOUT
MOVEM B,TCASE
JRST EOUTX
UCS1: SKIPG A,UCASC
JRST EOUTX
PBOUT
EOUTX: POP P,A
EOUTX0: POP P,B
EOUTX1: CAME A,UCASC
CAMN A,UCASL
JRST ESPCL
CAME A,LCASC
CAMN A,LCASL
JRST ESPCL
CAME A,QUOT
CAMN A,BRKC
JRST ESPCL
PBOUT
POPJ P,
ESPCL: PUSH P,A
SKIPLE A,QUOT
PBOUT
POP P,A
PBOUT
POPJ P,
; Primary input
.PBIN: PUSH P,B
MOVEI A,100
RFMOD ; Will echo be generated?
TRNE B,3B33!3B25
JRST [ MOVEI B,PBOUT0
EXCH B,0(P)
JRST .+2]
POP P,B
PBIN
POPJ P,
; Primary output
.PBOUT: PBOUT
PBOUT0: SKIPN SCRJFN
POPJ P,
PUSH P,B
MOVE B,A
MOVE A,SCRJFN
BOUT
PUSHJ P,SCRUPD
MOVE A,B
POP P,B
POPJ P,
.GTJFN: MOVE B,[XWD 100,101]
GTJFN0: SETOM RLACJ
GTJFN
JRST [ SETZM RLACJ
POPJ P,]
MOVEM A,IJFN
SETZM RLACJ
PUSH P,C
SETZ C,
MOVE B,A
SKIPE A,SCRJFN
JFNS
POP P,C
PUSHJ P,SCRUPD
MOVE A,B
JRST SKPRET
.NOUT: NOUT
POPJ P,
SKIPE A,SCRJFN
NOUT
JFCL
PUSHJ P,SCRUPD
MOVEI A,101
AOS (P)
POPJ P,
.SOUT: SKIPN A,SCRJFN
JRST .SOUT0
PUSH P,B
PUSH P,C
SOUT
PUSHJ P,SCRUPD
POP P,C
POP P,B
.SOUT0: MOVEI A,101
SOUT
POPJ P,
.PSOUT: SKIPE SCRJFN
PUSH P,A
PSOUT
SKIPN SCRJFN
POPJ P,
EXCH B,0(P)
PUSH P,C
MOVE A,SCRJFN
SETZ C,
SOUT
PUSHJ P,SCRUPD
MOVE A,B
POP P,C
POP P,B
POPJ P,
; Uuo handler
UUO: HRRO A,40
PUSHJ P,ERROUT
MOVEI A,400000
CIS
EIR
JRST COMLP
ERROUT: PUSH P,A
MOVEI A,101
DOBE
POP P,A
PUSHJ P,.PSOUT
MOVEI A,=1000
DISMS
MOVEI A,100
CFIBF
POPJ P,
; Convert interrupt character to code
CVINTC: CAIG A,33
JRST SKPRET
CAIE A,177
CAIN A,40
SKIPA
POPJ P,
CAIN A,40
MOVEI A,=29
CAIN A,177
MOVEI A,=28
JRST SKPRET
; Map fork one to one with this fork through page 177
; Call: A ; Fork handle
; PUSHJ P,MAPFRK
; Returns
; +1 ; Always. transparent
MAPFRK: PUSH P,C
PUSH P,D
PUSH P,B
MOVSI D,-177
MOVSI B,(A)
MOVSI A,400000
MOVSI C,160000
MAPFK1: HRR A,D
HRR B,D
PMAP
AOBJN D,MAPFK1
MOVE D,[XWD -10,770] ; DDT too
MAPFK2: HRR A,D
HRR B,D
PMAP
AOBJN D,MAPFK2
EXCH A,B
TRZ A,-1
HLR B,A
TRC B,400600
PMAP
HLRZ A,A
POP P,B
POP P,D
POP P,C
POPJ P,
INIFRK: MOVEM NCNX,CNX+FAC
MOVEI B,FAC
SFACS
MOVE B,[XWD FKLVT,FKCHT]
CIS
SIR
EIR
MOVSI B,(1B1!1B10!1B11)
AIC
POPJ P,
; Close and release JFN
CLRJFN: PUSH P,A
CLOSF
JFCL
POP P,A
RLJFN
JFCL
POPJ P,
; Macro for generating commands
DEFINE CC(STR,VAL)<
POINT 7,[ASCIZ \STR\
VAL]
>
; Top level commands
TOPC: XWD -1,SHSTAB
XWD -1,NULTAB
CC(<;*%x>,<JRST DOCOMT>)
CC(<flush.host>,<PUSHJ P,.FLUSH>)
CC(<list.connections>,<PUSHJ P,LSTCON>)
CC(<where.am.I>,<PUSHJ P,.WHERE>)
CC(<wait.for.any.active.connection>,<PUSHJ P,WATRET>)
CC(<retrieve.connection.under.name>,<PUSHJ P,RETCON>)
CC(<name.current.connection.to.be>,<PUSHJ P,.STNAM>)
CC(<write.modes.for.host>,<PUSHJ P,WRTMDF>)
CC(<!synch!>,<PUSHJ P,SNDSNC>)
CC(<!break!>,<PUSHJ P,SNDBRK>)
CC(<control>,<PUSHJ P,SNDCTL>)
XWD -1,CODTB
CC(<code>,<JRST [ MOVE TAB,CODTB
JRST SYMVAL]>)
CC(<exec>,<PUSHJ P,.EXEC>)
CC(<ddt>,<JRST 770000>)
CC(<reset>,<PUSHJ P,.RESET>)
CC(<logout>,<PUSHJ P,.LGOUT>)
CC(<quit>,<PUSHJ P,.QUIT>)
CC(<run>,<PUSHJ P,.RUN>)
CC(<socket.map>,<PUSHJ P,.SMAP>)
CC(<netstatus>,<PUSHJ P,.NSTS>)
CC(<help>,<PUSHJ P,.HELP>)
CC(<clear.output.character=>,<PUSHJ P,SETCBF>)
CC(<escape.character=>,<PUSHJ P,SETESC>)
XWD -1,YNTB
CC(<current.modes.are>,<PUSHJ P,PRCMD>)
CC(<no>,<JRST [SETCA NOA,
MOVE TAB,YNTB
JRST SYMVAN]>)
CC(<remote.mode>,<PUSHJ P,SETREM>)
CC(<local.mode>,<TRZ F,REMOTF>)
CC(<terminal.type.is>,<PUSHJ P,SETTRM>)
CC(<echo.mode.is>,<PUSHJ P,.ECHO>)
CC(<news>,<PUSHJ P,.NEWS>)
CC(<status.of>,<PUSHJ P,.STAT>)
CC(<disconnect>,<PUSHJ P,.DISC>)
CC(<connection.to>,<PUSHJ P,.CONN>)
COMTAB: XWD TOPC-.,TOPC
YNT: CC(<signal.waiting.output>,<MOVEM NOA,SWOFLG>)
CC(<typescript.to.file>,<PUSHJ P,SETSCR>)
CC(<divert.output.stream.to.file>,<PUSHJ P,SETDIV>)
CC(<fancy.command.interpret>,<SETCAM NOA,NFANCY>)
CC(<verbose>,<SETCAM NOA,CONCSF>)
CC(<concise>,<MOVEM NOA,CONCSF>)
CC(<attention.character:>,<PUSHJ P,SETATN>)
CC(<synch.character:>,<PUSHJ P,SETSNC>)
CC(<quote.prefix:>,<PUSHJ P,SETQOT>)
CC(<unshift.prefix:>,<PUSHJ P,SETUNS>)
CC(<case.shift.prefix.for>,<PUSHJ P,SETSHF>)
CC(<transparent.mode>,<MOVEM NOA,XPARNT(CNX)>)
CC(<lower>,<MOVEM NOA,LOWERF(CNX)>)
CC(<raise>,<MOVEM NOA,RAISEF(CNX)>)
CC(<line.buffer>,<MOVEM NOA,LNBFF(CNX)>)
CC(<character.mode>,<SETCAM NOA,LNBFF(CNX)>)
YNTB: XWD YNT-.,YNT
; Null table
NTP: CC(<>,<JFCL>)
NULTAB: XWD NTP-.,NTP
; Table of character code specifiers
CDTB: CC(<d%d*%d>,<PUSHJ P,SNDDCD>)
CC(<h%h*%h>,<PUSHJ P,SNDHCD>)
CC(<o%o*%o>,<PUSHJ P,SNDOCD>)
CC(<%o*%o>,<PUSHJ P,SNDOCT>)
CODTB: XWD CDTB-.,CDTB
; Command table for terminal modes
TRMT: CC(<lowercase>,<PUSHJ P,SETLWR>)
CC(<halfduplex>,<MOVEM NOA,HDX>)
CC(<fullduplex>,<SETCAM NOA,HDX>)
CC(<no>,<JRST [ SETCA NOA,
JRST SYMVAN]>)
TRMTAB: XWD TRMT-.,TRMT
; Command table for echo modes
ETP: CC(<local>,<JRST [ MOVEM NOA,ELCLF(CNX)
JRST CHGECH]>)
CC(<remote>,<JRST [ SETCAM NOA,ELCLF(CNX)
JRST CHGECH]>)
CC(<linefeed.for.carriage.return>,<MOVEM NOA,LFCRF(CNX)>)
CC(<control.character.echo.for>,<PUSHJ P,SETCOC>)
CC(<no>,<JRST [SETCA NOA,
JRST SYMVAN]>)
ECTAB: XWD ETP-.,ETP
; Command table for socket lookup
STP: CC(<FTP>,<PUSHJ P,.STFSK
3>)
CC(<RJS>,<PUSHJ P,.STFSK
5>)
CC(<Terminal.test>,<PUSHJ P,.STFSK
23>)
CC(<Netstatus>,<PUSHJ P,.STFSK
17>)
CC(<Date>,<PUSHJ P,.STFSK
15>)
CC(<Systat>,<PUSHJ P,.STFSK
13>)
CC(<Discard>,<PUSHJ P,.STFSK
11>)
CC(<Echo>,<PUSHJ P,.STFSK
7>)
CC(<logger>,<PUSHJ P,.STFSK
1>)
CC(<%o*%o>,<PUSHJ P,OCTFSK>)
CC(<name.for.connection.is>,<PUSHJ P,.STNAM>)
XWD -1,SETTAB
XWD -1,NULTAB
SKTTAB: XWD STP-.,STP
STB: CC(<no>,<JRST [ SETCA NOA,
MOVE TAB,SETTAB
JRST SYMVAN]>)
CC(<wait>,<MOVEM NOA,WATFLG>)
CC(<load.settings>,<MOVEM NOA,LODFLG>)
SETTAB: XWD STB-.,STB
; Host table
HTP: XWD -1,NHSTAB
XWD -1,SHSTAB
XWD -1,OCTB
HOSTAB: XWD HTP-.,HTP
; Octal number table
OCT: CC(<%o*%o>,<PUSHJ P,CVOCT>)
OCTB: XWD OCT-.,OCT
; Decimal number table
DCM: CC(<%d*%d>,<PUSHJ P,CVDEC>)
DCMTB: XWD DCM-.,DCM
; Letter table
LTR: CC(<%a>,<ILDB A,BPTR>)
LTRTB: XWD LTR-.,LTR
; Connection name table
NAMT: CC(<%n*%n>,<SETO A,>)
NAMTB: XWD -2,[XWD NAMT-.,NAMT
XWD -1,CONTAB]
; Case shift command table
SFTAB: CC(<lock.upper.case>,<MOVEI A,UCASL>)
CC(<char.upper.case>,<MOVEI A,UCASC>)
CC(<lock.lower.case>,<MOVEI A,LCASL>)
CC(<char.lower.case>,<MOVEI A,LCASC>)
SFTB: XWD SFTAB-.,SFTAB
; Socket map host table
SMTAB: XWD -1,HOSTAB
CC(<all>,<SETOB C,A>)
SMTB: XWD SMTAB-.,SMTAB
; Socket map state table
STTAB: Q←←0
FOR STAT IN (dead,clzd,pndg,lsng,rfcr,clw2,rfcs,opnd,clsw,datw,rfn1,clzw,rfn2,kild)<
CC(<STAT>,< IFL Q-=18,<MOVSI A,1⊗<=17-Q>>
IFG Q-=17,<MOVEI A,1<=35-Q>>>)
Q←←Q+1>
Q←←Q+1>
CC(<all>,<SETO A,>)
STTB: XWD STTAB-.,STTAB
; Symbol evaluator
SYMVAL: SETO NOA,
SYMVAN: MOVEM PTR,BPTR ; Save beginning of symbol
SYMLUP: PUSHJ P,GCH ; Get a character
CAIE A,"A"-100 ; Control-A
CAIN A,"H"-100 ; Or control-h
JRST DELCH ; Delete character
CAIN A,"R"-100
JRST RETYPE ; Control-R, retype line
CAIN A,"W"-100 ; Control-W
JRST DELWRD ; Delete word
CAIN A,"?" ; Question mark
JRST PRQUES ; Print options
CAIE A,33 ; Altmode or
CAIN A,37 ; Eol
JRST SYMEND ; Lookup
CAIE A,"," ; Comma
CAIN A," " ; Or space same thing
JRST SYMEND
IDPB A,PTR ; Else deposit into string
PUSHJ P,TRMST
SKIPE NFANCY
JRST SYMLPE
SETZ X, ; Clear X
MOVEM P,SVP ; Save P
MOVE Y,TAB ; Init Y
PUSHJ P,SYMLUK ; Lookup the current symbol
MOVE P,SVP ; Restore p
JUMPE X,[ DPB X,PTR; Smash null onto last character
MOVE A,PTR
BKJFN ; Back up pointer
JRST 4,.
MOVEM A,PTR
JRST DING]; And echo bell
SYMLPE: LDB A,PTR ; Symbol still ok, get char
PUSHJ P,ECHOIT
JRST SYMLUP ; And loop
DELCH: CAMN PTR,BPTR ; Delete character, any to delete?
JRST DING ; No, echo bell
MOVEI A,"\"
PUSHJ P,.PBOUT
LDB A,PTR
PUSHJ P,.PBOUT
MOVE A,PTR
BKJFN
JRST 4,.-1
MOVEM A,PTR
JRST SYMLUP
TRMST: PUSH P,A
PUSH P,PTR
SETZ A,
IDPB A,PTR
POP P,PTR
POP P,A
POPJ P,
DING: MOVEI A,7
PUSHJ P,.PBOUT
JRST SYMLUP
DELWRD: CAMN PTR,BPTR ; Delete word
JRST DING ; Nothing
MOVEI A,"#"
PUSHJ P,.PBOUT
PUSHJ P,.PBOUT
DELW0: MOVE PTR,BPTR
JRST SYMLUP
RETYPE: MOVE A,PTR
MOVEI B,0
IDPB B,A
MOVEI A,37
PUSHJ P,.PBOUT
MOVE A,LPTR
PUSHJ P,.PSOUT
JRST SYMLUP
; End of symbol, try lookup
SYMEND: MOVEM A,TERM ; Save terminator
PUSHJ P,TRMST
SETZ X,
MOVE Y,TAB
PUSHJ P,SYMLUK
JUMPE X,[ HRROI A,[ASCIZ / ? /]
PUSHJ P,ERROUT
MOVE A,TERM
CAIE A,37
JRST DELW0
JRST COMLP]
CAIE X,1 ; Exactly one symbol
JRST SYMAMB ; No. ambiguous
POP P,C ; Leave pointer to head in c
POP P,B ; Get pointer to tail of command
SYMCLP: ILDB A,B ; Copy to terminal
JUMPE A,SYMECL
MOVE D,TERM
SKIPE HDX
JRST NCOMP
SKIPN NFANCY
SKIPE CONCSF
NCOMP: CAIN D,33
PUSHJ P,.PBOUT
IDPB A,PTR
JRST SYMCLP
SYMECL: MOVEI A,40
MOVE D,TERM
CAIN D,33
JRST [ PUSHJ P,.PBOUT
JRST SYMEC1]
CAIE D,37
MOVE A,D
PUSHJ P,ECHOIT
SYMEC1: IDPB A,PTR
PUSHJ P,TRMST
XCT 1(B) ; Execute "value"
POPJ P, ; And return
XCT 2(B) ; If first value skips, execute 2nd
POPJ P,
SYMAMB: JUMPE X,DING ; Nothing left, go ding
POP P,C ; Leave pointer to head in c
POP P,B ; Get pointer to tail
ILDB A,B ; Get first ch of tail
JUMPN A,[SOJA X,SYMAMB] ; If not null, then loop
SYMAML: SOJLE X,SYMECL ; Else unique
SUB P,[XWD 2,2] ; Flush the junk
JRST SYMAML
PRQUES: PUSHJ P,ECHOIT
PUSHJ P,TRMST
SETZ X,
MOVE Y,TAB
PUSHJ P,SYMLUK ; Get all the possibilities
PRQUEL: JUMPE X,RETYPE ; All done, retype the line
MOVEI A,37
PUSHJ P,.PBOUT ; Eol
TRZ F,TMPF!TMPF2
PRQUEN: ILDB A,0(P)
JUMPE A,PRQUEE
CAIN A,"*"
JRST [ HRROI A,[ASCIZ /<any number of /]
PUSHJ P,.PSOUT
TRO F,TMPF
JRST PRQUEN]
CAIN A,"%"
JRST [ ILDB A,0(P)
CAIN A,"%"
JRST .+1
SETZ B,
CAIN A,"d"
HRROI B,[ASCIZ /decimal digit/]
CAIN A,"o"
HRROI B,[ASCIZ /octal digit/]
CAIN A,"h"
HRROI B,[ASCIZ /hexadecimal digit/]
CAIN A,"a"
HRROI B,[ASCIZ /alphabetic/]
CAIN A,"n"
HRROI B,[ASCIZ /alphameric/]
CAIN A,"s"
HRROI B,[ASCIZ /separator/]
CAIN A,"p"
HRROI B,[ASCIZ /punctuation mark/]
CAIN A,"x"
HRROI B,[ASCIZ /any character/]
JUMPE B,.+1
MOVEI A,"<"
TRNN F,TMPF
PUSHJ P,.PBOUT
MOVE A,B
PUSHJ P,.PSOUT
TRO F,TMPF2
JRST PRQUEQ]
PUSHJ P,.PBOUT
PRQUEQ: TRNN F,TMPF!TMPF2
JRST PRQUEN
HRROI A,[ASCIZ /'s>/]
TRZE F,TMPF2
HRROI A,[ASCIZ /s>/]
TRZN F,TMPF
HRROI A,[ASCIZ />/]
PUSHJ P,.PSOUT
JRST PRQUEN
PRQUEE: SUB P,[XWD 2,2] ; Flush pointer to end
SOJA X,PRQUEL ; And loop
; Lookup symbol
; Operates recursively and accumulates a list of things on the stack
SYMLUK: PUSH P,SVP ; Save old bottom
MOVEM P,SVP ; Svp points to chain of svp
TLNE Y,7000 ; Byte pointer in y?
JRST SYMLK1 ; No aobjn word
PUSH P,Y ; Yes, sve y
MOVE D,BPTR ; Get pointer to symbol
SYMLKL: ILDB A,D ; Get character from input
ILDB B,Y ; And from table entry
PUSHJ P,SYMCMP ; Compare the characters
JRST SYMNEQ ; Not equal
JUMPN A,SYMLKL ; Continue until null
SYMEQL: MOVE A,Y
BKJFN ; Back up pointer to tail
JRST [ CAIE A,600150 ; Don't bomb out if empty list--
JRST 4,. ; (non-negative AOBJN pointer)
JRST SYMNEX]
MOVEM A,Y
EXCH Y,-2(P) ; Pointer to tail to stack, get ret
POP P,A ; Pointer to head
POP P,SVP ; Restore svp
PUSH P,A ; Pointer to head back to stack
AOJA X,0(Y) ; Return and count items
SYMNEQ: JUMPE A,SYMEQL ; If input ends first, then substring
SYMNEX: SUB P,[XWD 1,1] ; Else flush saved y
POP P,SVP ; Restore svp
POPJ P, ; And return
SYMLK1: PUSH P,Z ; Save z
MOVE Z,Y ; Use as place to count y
SYMLK3: MOVE Y,0(Z) ; Loop to here for each item
PUSHJ P,SYMLUK ; Do this item
AOBJN Z,SYMLK3 ; Loop over all things
MOVE A,P ; Get p
SUB A,[XWD 1,1]
CAMN A,SVP ; Any items saved on stack?
JRST SYMLK4 ; No, shuffle not needed
MOVE A,SVP ; Get base of stack
MOVE Z,1(A) ; Restore z
POP A,SVP ; Restore svp
MOVE Y,0(A) ; Get return
MOVEI B,0(A) ; Where to blt to
HRLI B,3(A) ; And where from
BLT B,-3(P) ; Copy stack down
SUB P,[XWD 3,3]
JRST 0(Y) ; Return
SYMLK4: POP P,Z
POP P,SVP
POPJ P,
SYMCMP: CAIN B,"*" ; Asterisk
JRST SYMMNY ; Means any number of
CAIN B,"%" ; Percent
JRST SYMCLS ; Means character class
CAIN B,"#" ; Pound sign
JRST SYMNCL ; Means not character class
SYMCM2: PUSH P,B
PUSH P,A
XOR A,B
TRZ B,40 ; Ignore case of B
CAIL B,"A" ; Then if B has
CAILE B,"Z" ; a letter
CAIA
TRZ A,40 ; Then ignore case of difference
SKIPN A
AOS -2(P)
POP P,A
POP P,B
POPJ P,
SYMMNY: PUSH P,Y ; Save where we are in table entry
ILDB B,Y ; Get what we are doing many of
PUSHJ P,SYMCMP ; Check match
JRST SYMMNN ; Not equal
ILDB B,Y ; See if next is also equal
PUSHJ P,SYMCMP
JRST [ EXCH A,0(P) ; Not equal, get back y, save a
BKJFN
JRST 4,.
MOVEM A,Y
POP P,A
JRST SKPRET]
SUB P,[XWD 1,1] ; Matches next thing, use it instead
SKPRET: AOS (P)
POPJ P,
SYMMNN: SUB P,[XWD 1,1] ; Go to next thiing
ILDB B,Y
JRST SYMCMP
SYMCLS: ILDB B,Y ; Get class indicator
CAIN B,"%" ; %% means %
JRST SYMCM2
CAIN B,"d" ; d means decimal digit
JRST SYMDEC
CAIN B,"o" ; o means octal digit
JRST SYMOCT
CAIN B,"h"
JRST SYMHEX
CAIN B,"a" ; a means alphabetic
JRST SYMALP
CAIN B,"n" ; n means alphameric
JRST SYMALM
CAIN B,"s" ; s means separator
JRST SYMSEP
CAIN B,"p" ; p for punctuation
JRST SYMPNC
CAIN B,"x"
JRST SYMANY
POPJ P, ; Else fail
SYMNCL: PUSHJ P,SYMCLS
AOS (P)
POPJ P,
SYMANY: AOS (P)
POPJ P,
SYMDEC: CAIG A,"9"
CAIGE A,"0"
POPJ P,
JRST SKPRET
SYMOCT: CAIG A,"7"
CAIGE A,"0"
POPJ P,
JRST SKPRET
SYMHEX: CAIG A,"9"
CAIGE A,"0"
JRST SYMHE1
JRST SKPRET
SYMHE1: TRZ A,40
CAIG A,"F"
CAIGE A,"A"
POPJ P,
JRST SKPRET
SYMALM: PUSHJ P,SYMDEC
JRST SYMALP
JRST SKPRET
SYMALP: TRZ A,40
CAIG A,"Z"
CAIGE A,"A"
POPJ P,
JRST SKPRET
SYMSEP:
SYMPNC: POPJ P,
; News
.NEWS: MOVEI B,367
MOVEM B,FSKT
MOVEI A,361
MOVEM A,FHSTN
MOVEM A,FHST
JRST CONNX1
; Connect.to
.CONN: MOVE TAB,HOSTAB
PUSHJ P,SYMVAL
MOVEM A,FHSTN
CONNX: MOVEM A,FHST
SETOM FSKT
CONNX1: MOVSI X,-NCONN
SKIPE SNDJFN(X)
AOBJN X,.-1
JUMPGE X,[ERROR [ASCIZ /too many connections./]]
HRRZS NCNX,X
MOVE A,NCNX
IMULI A,3
ADDI A,CONNAM
HRLI A,440700
MOVEI B,1(X)
MOVEI C,010
NOUT
JFCL
IBP A
HRLI X,(<MOVEI A,0>)
MOVEM X,1(A)
SKIPL FSKT
JRST CONN2
PUSHJ P,DEFSKT
PUSHJ P,SETMOD
JRST CONN2 ; Settings not changed
HRROI A,[ASCIZ /(settings loaded) /]
SKIPN CONCSF
PUSHJ P,.PSOUT
; JRST CONN2
CONN2: HRROI A,[ASCIZ /is /]
PUSHJ P,.PSOUT
PUSHJ P,ASNSKT
PUSHJ P,DOICP ; Do icp
JRST [ SKIPN WATFLG ; Failed. wait?
JRST CONFL ; No.
HRROI A,[ASCIZ /incomplete on first try.
Trying again ... /]
SKIPG WATFLG
PUSHJ P,.PSOUT
MOVMS WATFLG
MOVEI A,=10000
DISMS
JRST .-2]
MOVEI A,7
MOVEI B,20
SKIPLE WATFLG
PUSHJ P,.PBOUT
SOJG B,.-2
HRROI A,[ASCIZ /complete/]
PUSHJ P,.PSOUT
MOVEI A,400000
DIR
SKIPE A,SNDFRK(NCNX)
JRST CONN3
MOVSI A,(1B1)
CFORK
JRST [ JSP X,CONFL0
ASCIZ /can't create send fork./]
MOVEM A,SNDFRK(NCNX)
PUSHJ P,MAPFRK
CONN3: PUSHJ P,INIFRK
SKIPE A,RCVFRK(NCNX)
JRST CONN4
MOVSI A,(1B1)
CFORK
JRST [ JSP X,CONFL1
ASCIZ /can't create receive fork./]
MOVEM A,RCVFRK(NCNX)
PUSHJ P,MAPFRK
CONN4: PUSHJ P,INIFRK
MOVE A,IJFN
MOVEM A,SNDJFN(NCNX)
MOVE A,JJFN
MOVEM A,RCVJFN(NCNX)
SETZM IJFN
SETZM JJFN
MOVE CNX,NCNX
HLRE A,CONTAB
MOVNS A
ADD A,CONTAB
HRRZ B,CNX
IMULI B,3
ADDI B,CONNAM
HRLI B,440700
MOVEM B,(A)
MOVSI B,-1
ADDM B,CONTAB
MOVN A,LSKT(CNX)
ASH A,-1
MOVSI B,(1B0)
ROT B,(A)
IORM B,SKTMSK
SETZM SAVSWT(CNX)
MOVEI B,SEND
MOVE A,SNDFRK(CNX)
FFORK
SFORK
MOVE A,RCVFRK(CNX)
MOVEI B,RECV
FFORK
SFORK
TRO F,REMOTF
MOVEI A,400000
EIR
MOVEI A,"."
PUSHJ P,.PBOUT
POPJ P,
CONFL1:CONFL0: HRROI A,[ASCIZ /,
but /]
PUSHJ P,.PSOUT
PUSHJ P,RELCON
JRST CONFLX
CONFL: PUSH P,A
HRROI A,[ASCIZ /incomplete,
because /]
PUSHJ P,.PSOUT
POP P,A
CONFLX: PUSHJ P,.PSOUT
POPJ P,
; Assign socket for connection
ASNSKT: SETCM A,SKTMSK
PUSH P,B
JFFO A,ASNSK1
MOVEI B,177
ASNSK1: MOVE A,B
POP P,B
LSH A,1
POPJ P,
; Perform icp
DOICP: MOVEM A,LSKT(NCNX) ; Remember local socket
MOVE A,PTR
IBP A ; Use area past command string
PUSH P,A ; Save start of string
HRROI B,[ASCIZ /NET:/]
SETZ C,
SOUT
PUSH P,A ; Save where socket number is
MOVE B,LSKT(NCNX)
MOVE C,[1B2+1B3+3B17+10]
NOUT
JRST 4,.-1
MOVEI B,"."
IDPB B,A
SETZ C,
MOVE B,FHST
TLNE B,-1 ; Number ?
JRST [ SOUT ; No, string, use it
JRST ICP9]
MOVEI C,10
NOUT
JRST 4,.-1
ICP9: MOVEI B,"-"
IDPB B,A
PUSH P,A ; Save where fs begins
MOVE B,FSKT
MOVEI C,10
NOUT
JRST 4,.-1
HRROI B,[ASCIZ /;T/]
SETZ C,
SOUT
; JRST ICPA
ICPA: MOVE B,-2(P) ; Get beginning of string
MOVEI A,400000
DIR
MOVSI A,1 ; Short form, string pointer
GTJFN
JRST [ JSP X,ICPFL2
ASCIZ /IMP is disconnected./]
MOVEM A,IJFN ; Save jfn to be released if int
MOVEI A,400000
EIR ; Interrupts
TIME
MOVEM A,ICPTIM
MOVE A,IJFN
MOVE B,[XWD 400001,200000]
PUSHJ P,.OPENF
JRST [ PUSHJ P,HSTCHK
JRST [ JSP X,ICPFL2
ASCIZ /host is disconnected./]
JSP X,ICPFL2
ASCIZ /host is rejecting./]
MOVE A,IJFN
BIN ; Get socket number to use
MOVEI A,400000
DIR
MOVE A,IJFN
CLOSF
JFCL
SETZM IJFN
MOVEI A,400000
EIR
POP P,A ; Back to beginning of fs
MOVEI C,10
NOUT
JRST 4,.-1
HRROI B,[ASCIZ /;T/]
SETZ C,
SOUT
POP P,A ; Get loc of ls
MOVE B,LSKT(NCNX)
ADDI B,2
MOVE C,[1B2+1B3+3B17+10]
NOUT
JRST 4,.-1
MOVEI B,"."
IDPB B,A
; JRST ICPB
ICPB: MOVE B,0(P) ; Beginning of string
MOVEI A,400000
DIR
MOVSI A,1
GTJFN
JRST [ JSP X,ICPFL1
ASCIZ /no send JFN/]
MOVEM A,IJFN
POP P,B
MOVSI A,1
GTJFN
JRST [ JSP X,ICPFL0
ASCIZ /no recv JFN/]
MOVEM A,JJFN
MOVEI A,400000
EIR
MOVE A,IJFN
MOVE B,[XWD 103402,100000]
OPENF ; Open send, don't wait
JRST [ JSP X,ICPFL0
ASCIZ /send connection can't be opened./]
MOVE A,JJFN
MOVE B,[XWD 100010,200000]
PUSHJ P,.OPENF
JRST [ JSP X,ICPFL0
ASCIZ /receive connection can't be opened./]
MOVE A,IJFN
PUSHJ P,OPNWAT ; Wait for connection to be opened
JRST [ JSP X,ICPFL0
ASCIZ /send connection was not successfully opened./]
TIME
SUBM A,ICPTIM
AOS (P)
POPJ P,
ICPFL2: SUB P,[XWD 2,2]
ICPFL1: SUB P,[XWD 1,1]
ICPFL0: SETOM ICPTIM
PUSHJ P,RELCON
HRROI A,(X)
POPJ P,
RELCON: MOVEI A,400000
DIR
SKIPE A,IJFN
PUSHJ P,CLRJFN
SKIPE A,JJFN
PUSHJ P,CLRJFN
SETZM IJFN
SETZM JJFN
MOVEI A,400000
EIR
POPJ P,
OPNWAT: PUSH P,A
JRST OPNWT0
.OPENF: PUSH P,A
TLO B,3000
OPENF
JRST OPNFL1
OPNWT0: SETOM NTICNT
MOVEI B,24
MOVSI C,777700+NTICHN
MTOPR ; Cause fsm state changes to interrupt
OPNWTL: SETOM NTICNT
MOVE A,0(P)
GDSTS
ROT B,4
ANDI B,17
CAIN B,7
JRST OPNWIN
CAIE B,6
JRST OPNFL
MOVEI A,=100000
AOSN NTICNT ; Increment to 0 if waiting
OPNWTK: DISMS
JRST OPNWTL
OPNWIN: POP P,A
MOVEI B,24
SETO C,
MTOPR
JRST SKPRET
OPNFL1: POP P,A
POPJ P,
OPNFL: POP P,A
CLOSF
JFCL
POPJ P,
NTIINT: MOVEM A,NTIIA
AOSN NTICNT
DEBRK
HRRZ A,RETPC3
CAIE A,OPNWTK
CAIN A,OPNWTK+1 ; Either two locations is ok
SKIPA A,[XWD 10000,OPNWTL]
SKIPA A,NTIIA
MOVEM A,RETPC3
DEBRK
; Disconnect
.DISC: MOVE A,TERM
MOVE X,CNX
CAIN A,37
JRST DISC1
SKIPL TAB,CONTAB
POPJ P,
PUSHJ P,SYMVAL
MOVE X,A
DISC1: MOVEI A,400000
DIR
CAMN X,CNX
TRZ F,REMOTF
MOVE A,ABNCNX ; Might be abncnx
SETOM ABNCNX ; Clear it
CAMN X,A ; And if it was
SETOM ABNLCK ; Unlock abnlck
SKIPN RCVJFN(X)
POPJ P, ; No connection
MOVE A,RCVFRK(X)
FFORK
SKIPE A,RCVJFN(X)
PUSHJ P,CLRJFN
SKIPE A,SNDJFN(X)
PUSHJ P,CLRJFN
SETZM RCVJFN(X)
SETZM SNDJFN(X)
MOVN A,LSKT(X)
ASH A,-1
MOVSI B,(1B0)
ROT B,(A)
ANDCAM B,SKTMSK
IMULI X,3 ; Compute pointer to this name
ADDI X,CONNAM
HRLI X,440700
MOVE Y,CONTAB
CAME X,0(Y) ; Search for entry in contb
AOBJN Y,.-1
MOVE A,1(Y) ; Move entries above here, down to
MOVEM A,0(Y) ; fill in the gap
AOBJN Y,.-2
MOVSI X,1
ADDM X,CONTAB ; One less entry in contb
MOVEI A,400000
EIR
POPJ P,
; Set name for connection
.STNAM: MOVE TAB,NAMTB
PUSHJ P,SYMVAL
JUMPGE A,NAMINU
HRRZ A,NCNX
IMULI A,3
ADDI A,CONNAM
HRLI A,440700
MOVE B,BPTR
MOVEI C,=8
LDB D,PTR ; Get terminator
SOUT ; Copy through it
SETZ B,
DPB B,A ; Replace terminator with null
MOVE B,NCNX
HRLI B,(<MOVEI A,>)
MOVEM B,1(A)
POPJ P,
NAMINU: ERROR [ASCIZ /name already in use/]
; Wait for a connection wanting to print
WATRET: MOVSI X,-NCONN
WATREL: SKIPG SNDJFN(X)
JRST WATREX
SKIPG SAVINC(X)
JRST WATREX
HRROI A,[ASCIZ /
connection /]
PUSHJ P,.PSOUT
HRRZ A,X
IMULI A,3
HRROI A,CONNAM(A)
PUSHJ P,.PSOUT
HRROI A,[ASCIZ / ready. /]
PUSHJ P,.PSOUT
HRRZ A,X
JRST RETCO1
WATREX: AOBJN X,WATREL
MOVEI A,=10000
DISMS
JRST WATRET
; Retrieve connection
RETCON: SKIPL TAB,CONTAB
JRST [ HRROI A,[ASCIZ /
No connections.
/]
PUSHJ P,.PSOUT
POPJ P,]
PUSHJ P,SYMVAL
RETCO1: MOVEM A,CNX
TRO F,REMOTF
POPJ P,
; List connections
LSTCON: TRZ F,TMPF
MOVE X,CONTAB
JUMPGE X,LSTCOX
LSTCOL: HRROI A,[ASCIZ /
-Name- -From- --To--
/]
TRON F,TMPF
PUSHJ P,.PSOUT
SETZ C,
MOVE A,(X)
PUSHJ P,.PSOUT
MOVE B,1(A)
MOVEI A,11
PUSHJ P,.PBOUT
MOVEI A,101
MOVE B,SNDJFN(B)
MOVE C,[BYTE (3)0,0,1,1,0,0,0(5)0,0,2]
JFNS
SKIPE A,SCRJFN
JFNS
PUSHJ P,SCRUPD
MOVEI A,37
PUSHJ P,.PBOUT
LSTCOX: AOBJN X,LSTCOL
HRROI A,[ASCIZ /
No saved connections./]
TRZN F,TMPF
PUSHJ P,.PSOUT
POPJ P,
; Set mode switches
SETMOD: SKIPN LODFLG
POPJ P,
PUSHJ P,OPNMDF ; Open mode file
POPJ P, ; Non-existent
JFCL ; Ok if we can't write
PUSHJ P,SCHMDF ; Search mode file for the right host
JRST STMDX ; Not found
MOVE C,PMODSW
BIN
MOVEM B,@0(C)
AOBJN C,.-2
AOS (P)
STMDX: PUSHJ P,CLRJFN
SETZM IJFN
POPJ P,
WRTMDF: MOVE TAB,HOSTAB
PUSHJ P,SYMVAL
PUSHJ P,DEFSKT
PUSHJ P,OPNMDF ; Open it
JFCL ; Can't find it
JRST [ HRROI A,[ASCIZ /Cannot write TELNET.MODES/]
PUSHJ P,.PSOUT
SKIPE A,IJFN
PUSHJ P,CLRJFN
SETZM IJFN
POPJ P,]
PUSHJ P,SCHMDF ; See if old settings exist
JRST WRTMD1 ; No, ok to write
HRROI A,[ASCIZ /Confirm /]
PUSHJ P,.PSOUT
PUSHJ P,GCH
CAIE A,37
JRST [ HRROI A,[ASCIZ /Not done./]
PUSHJ P,.PSOUT
JRST WRTMDX]
MOVE A,IJFN
WRTMD1: MOVE B,FHSTN
ROUT
MOVE B,FSKT
BOUT
MOVE NCNX,CNX
MOVE C,PMODSW
MOVE B,@0(C)
BOUT
AOBJN C,.-2
WRTMDX: MOVE A,IJFN
PUSHJ P,CLRJFN
SETZM IJFN
POPJ P,
PMODSW: XWD -NMODSW,MODSWP
MODSWP: FOR A IN (LFCRF,ELCLF,LNBFF,RAISEF,JUNK,ECHCOC,LOWERF,JUNK,JUNK,JUNK),
< XWD NCNX,A
>
SCHMDF: MOVEI C,0 ; Start with word 0
SCHMDL: RIN ; Read it
JUMPE B,CPOPJ ; End of file
CAME B,FHSTN ; Correct host?
JRST SCHMDN ; Not this, try next
BIN ; Get socket
CAMN B,FSKT ; Correct one?
JRST SKPRET
SCHMDN: ADDI C,NMODSW+2
JRST SCHMDL
OPNMDF: MOVEI A,400000
DIR
HRROI B,[ASCIZ /<DOCUMENTATION>TELNET.MODES/]
MOVSI A,1
GTJFN
JRST [ MOVEI A,400000
EIR
POPJ P,]
MOVEM A,IJFN
MOVEI A,400000
EIR
MOVE A,IJFN
MOVE B,[XWD 440000,300000]
OPENF
JRST [ MOVE A,IJFN
TRZE B,100000
JRST .-1
PUSHJ P,CLRJFN
SETZM IJFN
POPJ P,]
TRNE B,100000
AOS (P)
JRST SKPRET
; Status.of
.STAT: MOVEI NCNX,NCONN ; Use this cnx for status
MOVE TAB,HOSTAB
PUSHJ P,SYMVAL
MOVEM A,FHST
PUSHJ P,DEFSKT
PUSHJ P,SETMOD
JFCL
STAT1: MOVEI NCNX,NCONN ; For late-comers
MOVEI A,74 ; Local socket for icp
PUSHJ P,DOICP
JRST STAT2
PUSHJ P,RELCON ; Flush things set up by doicp
HRROI A,[ASCIZ /logger operational./]
STAT2: PUSHJ P,.PSOUT
POPJ P,
; Exec
.EXEC: HRROI B,[ASCIZ /<SYSTEM>EXEC.SAV/]
MOVSI C,(1B0) ; CAUSE INTERRUPTS TO GO OFF
MOVSI A,100001
JRST SBGET
; Run
.RUN: MOVSI A,100003
MOVE B,[XWD 100,101]
SETZ C,
JRST SBGET
; Socket.map
.SMAP: SETOM FAC
SETOM FAC+1
MOVE A,TERM
CAIN A,37
JRST SMAPD
MOVE TAB,SMTB
PUSHJ P,SYMVAL
TLNN A,-1
MOVE C,A
MOVEM C,FAC+0
MOVE A,TERM
CAIN A,37
JRST SMAPD
SETZM FAC+1
HRROI A,[ASCIZ /(states) /]
PUSHJ P,.PSOUT
SMAPL: MOVE TAB,STTB
PUSHJ P,SYMVAL
IORM A,FAC+1
MOVE A,TERM
CAIN A,","
JRST SMAPL
SMAPD: MOVEI C,1
JRST NTSTSD
; Netstatus
.NSTS: MOVEI C,0
NTSTSD: HRROI B,[ASCIZ /<SUBSYS>NETSTAεSAV/]
MOVSI A,100001
SBGET: PUSH P,B
PUSHJ P,GTJFN0
JRST [ POP P,A
TLNN A,-1
PUSHJ P,.PSOUT
ERROR [ASCIZ / not available./]]
SUB P,[XWD 1,1]
MOVEI A,400000
DIR
MOVSI A,(1B1!1B3)
MOVEI B,FAC
CFORK
JRST [ HRROI A,[ASCIZ /No forks available./]
JRST GETF]
MOVEM A,SPCFRK
HRLZ A,SPCFRK
HRR A,IJFN
GET
SETZM IJFN
MOVEI A,400000
EIR
JUMPGE C,SBGET4
DIR
MOVE A,ESCCOD
DTI
MOVE A,CBFCOD
DTI
SBGET4: PUSH P,C
MOVEI A,100
MOVE B,TTCOC0
MOVE C,TTCOC1
SFCOC
MOVE B,TTMOD0
SFMOD
HRRZ B,0(P)
MOVE A,SPCFRK
SFRKV
WFORK
MOVEI A,400000
DIR
MOVE A,SPCFRK
KFORK
SETZM SPCFRK
POP P,C
JUMPGE C,SBGET5
MOVEI A,ESCCHN
HRL A,ESCCOD
ATI
MOVEI A,CBFCHN
HRL A,CBFCOD
ATI
SBGET5: MOVEI A,400000
EIR
POPJ P,
GETF: PUSH P,A
MOVEI A,400000
EIR
SKIPE A,IJFN
PUSHJ P,CLRJFN
SETZM IJFN
POP P,A
JRST .PSOUT
; Set escape character
SETESC: PUSHJ P,SETICH
ESCAPE
ESCCOD
ESCCHN
POPJ P,
SETCBF: PUSHJ P,SETICH
CBFCHR
CBFCOD
CBFCHN
POPJ P,
SETICH: MOVE X,0(P)
ADDI X,3
EXCH X,0(P)
PUSHJ P,.PBIN
CAIN A,"?"
JRST PRESC
PUSH P,A
PUSHJ P,CVINTC
JRST SETED
PUSH P,A
MOVEI A,400000
DIR
POP P,A
MOVE B,0(P)
MOVEM B,@0(X)
EXCH A,@1(X)
DTI
HRLZ A,@1(X)
HRRI A,@2(X)
ATI
MOVE A,0(P)
CAIL A,40
JRST SETE1
MOVEI A,"↑"
PUSHJ P,ECHOIT
MOVEI A,100
ADDM A,0(P)
SETE1: POP P,A
PUSHJ P,ECHOIT
MOVEI A,400000
EIR
POPJ P,
SETED: POP P,A
MOVEI A,7
PUSHJ P,.PBOUT
JRST SETESC
PRESC: HRROI A,[ASCIZ /
control-@ through control-Z
altmode
rubout
space
/]
PUSHJ P,.PSOUT
MOVE A,LPTR
PUSHJ P,.PSOUT
JRST SETESC
; Set terminal modes
SETTRM: MOVE TAB,TRMTAB
JRST SYMVAL
; Set attention character
SETATN: SETOM BRKC
JUMPGE NOA,CPOPJ
PUSHJ P,.PBIN
PUSHJ P,ECHOIT
MOVEM A,BRKC
POPJ P,
; Set synch character
SETSNC: SETOM SYNC
JUMPGE NOA,CPOPJ
PUSHJ P,.PBIN
PUSHJ P,ECHOIT
MOVEM A,SYNC
POPJ P,
; Set single charcter quote prefix
SETQOT: SETOM QUOT
JUMPGE NOA,CPOPJ
PUSHJ P,.PBIN
PUSHJ P,ECHOIT
MOVEM A,QUOT
POPJ P,
; Set unshift prefix
SETUNS: SETOM UNSFT
JUMPGE NOA,CPOPJ
PUSHJ P,.PBIN
PUSHJ P,ECHOIT
MOVEM A,UNSFT
POPJ P,
; Set case shift prefixes
SETSHF: PUSH P,NOA ; Save noa
MOVE TAB,SFTB
PUSHJ P,SYMVAL
POP P,NOA
SETOM (A) ; Turn off prefix
JUMPGE NOA,CPOPJ ; Done if "no"
PUSH P,A
PUSHJ P,.PBIN
PUSHJ P,ECHOIT
MOVEM A,@(P)
SUB P,[XWD 1,1]
POPJ P,
; Echo.mode.is
.ECHO: MOVE TAB,ECTAB
JRST SYMVAL
CHGECH: HRROI A,[ASCIZ /
A half-duplex terminal (which I believe you have) will not work well with
remote echoing./]
SKIPE HDX
SKIPE ELCLF(CNX)
SKIPA
PUSHJ P,.PSOUT
SKIPN A,SNDJFN
POPJ P,
MOVEI B,TELNEC
SKIPN ELCLF(CNX)
MOVEI B,TELECH
BOUT
MOVEI B,21
MTOPR
POPJ P,
; Terminal has lower case
SETLWR: MOVEM NOA,TRMLWC
MOVSI B,(1B3)
JUMPGE NOA,SETLW1
IORM B,TTMODR
IORB B,TTMODC
JRST SETLW2
SETLW1: ANDCAM B,TTMODR
ANDCAB B,TTMODC
SETLW2: MOVEI A,101
STPAR
POPJ P,
SNDSNC: SKIPN A,SNDJFN(CNX)
POPJ P,
MOVEI B,22
MTOPR ; Send ins
MOVEI B,TELSNC
BOUT ; And sync character
MOVEI B,21
MTOPR
POPJ P,
; Set control character echoing
SETCOC: PUSHJ P,GCH
CAIN A,"?"
JRST SETCOQ
PUSHJ P,ECHOIT
SETCO2: CAIN A,37
MOVEI A,15
MOVEM A,TERM
PUSHJ P,.PBIN
PUSHJ P,ECHOIT
EXCH A,TERM
ANDI A,37
MOVSI B,400000
MOVNS A
ROT B,(A)
SKIPN NOA
ANDCAM B,ECHCOC(CNX)
SKIPE NOA
IORM B,ECHCOC(CNX)
MOVE A,TERM
CAIE A,37
JRST [ CAIE A,40
CAIN A,","
JRST SETCOC
JRST SETCO2]
POPJ P,
SETCOQ: HRROI A,[ASCIZ /
control characters or letter equivalents/]
PUSHJ P,.PSOUT
MOVE A,LPTR
PUSHJ P,.PSOUT
JRST SETCOC
SETCOE: MOVEI A,7
PUSHJ P,.PBOUT
JRST SETCOC
; Print current modes
PRCMD: MOVSI X,-NPMDTB
PRCMD1: MOVEI A,37
PUSHJ P,.PBOUT
MOVSI C,CNX
HLR C,PCMDTB(X)
HRROI A,[ASCIZ /no /]
SKIPN @C
PUSHJ P,.PSOUT
HRRO A,PCMDTB(X)
PUSHJ P,.PSOUT
AOBJN X,PRCMD1
HRROI A,[ASCIZ /
Special characters:
/]
PUSHJ P,.PSOUT
MOVSI X,-NSPECH
PCSLP: HLRZ B,CSTAB(X)
SKIPG (B)
JRST PCSLPN
HRRO A,CSTAB(X)
PUSHJ P,.PSOUT
MOVEI A,11
PUSHJ P,.PBOUT
MOVE A,(B)
PUSHJ P,.PBOUT
PCSLPE: MOVEI A,37
PUSHJ P,.PBOUT
PCSLPN: AOBJN X,PCSLP
SKIPE D,ECHCOC(CNX)
SKIPN ELCLF(CNX)
POPJ P, ; Done if not local echo or no coc
HRROI A,[ASCIZ /
Local echo for control /]
PUSHJ P,.PSOUT
PRCM2: JFFO D,.+1
MOVSI B,400000
MOVN C,D+1
ROT B,(C)
ANDCAM B,D
JUMPN D,PRCM1
HRROI A,[ASCIZ /and /]
CAME B,ECHCOC(CNX)
PUSHJ P,.PSOUT
PRCM1: MOVEI A,100(D+1)
PUSHJ P,.PBOUT
JUMPE D,CPOPJ
HRROI A,[ASCIZ /, /]
PUSHJ P,.PSOUT
JRST PRCM2
PCMDTB: XWD RAISEF,[ASCIZ /Raise/]
XWD LOWERF,[ASCIZ /Lower/]
XWD ELCLF,[ASCIZ /Local echo/]
XWD LFCRF,[ASCIZ /Echo linefeed for carriage return/]
XWD LNBFF,[ASCIZ /Line buffer/]
NPMDTB←←.-PCMDTB
CSTAB: XWD ESCAPE,[ASCIZ /Escape: /]
XWD CBFCHR,[ASCIZ /Clrobf: /]
XWD QUOT,[ASCIZ /Quote: /]
XWD UNSFT,[ASCIZ /Unshift:/]
XWD LCASC,[ASCIZ /Char.lower:/]
XWD LCASL,[ASCIZ /Lock.lower:/]
XWD UCASC,[ASCIZ /Char.upper:/]
XWD UCASL,[ASCIZ /Lock.upper:/]
XWD BRKC,[ASCIZ /Break: /]
XWD SYNC,[ASCIZ /Synch: /]
NSPECH←←.-CSTAB
; Help
.HELP: MOVEI A,400000
DIR
HRROI B,[ASCIZ /<DOCUMENTATION>TELNET.HELP/]
MOVSI A,100001
GTJFN
JRST [ MOVEI A,400000
EIR
HRROI A,[ASCIZ /Help file not found./]
JRST .PSOUT]
MOVEM A,IJFN
MOVEI A,400000
EIR
MOVE A,IJFN
MOVE B,[XWD 70000,200000]
OPENF
JRST [ MOVE A,IJFN
PUSHJ P,CLRJFN
SETZM IJFN
HRROI A,[ASCIZ /Help file can't be opened./]
JRST .PSOUT]
TYPLP: MOVEI X,=20
TYPLP1: MOVE A,IJFN
MOVE B,[POINT 7,COMBUF]
MOVEI C,200*5-3
MOVEI D,12
SIN
GTSTS
TLNE B,1000
JRST ETYPL
MOVEI A,101
MOVE B,[POINT 7,COMBUF]
MOVEI C,200*5-3
MOVEI D,12
PUSHJ P,.SOUT
SOJG X,TYPLP1
CAIGE C,200*5-3-2
JRST TYPLP1
HRROI A,[ASCIZ /
More help? /]
PUSHJ P,.PSOUT
; JRST TYPAL
TYPAL: PUSHJ P,.PBIN
CAIE A,"Y"
CAIN A,"y"
JRST TYPMO
CAIE A,"N"
CAIN A,"n"
JRST TYPNO
MOVEI A,7
PUSHJ P,.PBOUT
JRST TYPAL
TYPMO: HRROI A,[ASCIZ /Yes
/]
PUSHJ P,.PSOUT
JRST TYPLP
TYPNO: HRROI A,[ASCIZ /No
/]
PUSHJ P,.PSOUT
JRST ETYPX
ETYPL: SUBI C,200*5-3
SOUT
ETYPX: MOVE A,IJFN
PUSHJ P,CLRJFN
SETZM IJFN
POPJ P,
; Typescript to a file
SETSCR: PUSHJ P,UGTAD
MOVEM B,SCRTIM ; Time of last typescript entry
SETZM SCRCNT ; Characters output since last openf
MOVEI A,400000
DIR
SETZ A,
EXCH A,SCRJFN
SKIPLE A
PUSHJ P,CLRJFN
JUMPGE NOA,[MOVSI A,400001
HRROI B,[ASCIZ /TELNET.TYPESCRIPT;T/]
GTJFN
JRST [ MOVEI A,400000
EIR
POPJ P,]
PUSH P,A
MOVE B,[XWD 70000,20000]
OPENF
JRST [ POP P,A
RLJFN
JFCL
MOVEI A,400000
EIR
POPJ P,]
HRROI B,[ASCIZ /
TELNET typescript file started at /]
SETZ C,
SOUT
SETO B,
MOVE C,[1B1+1B7+1B12+1B17]
ODTIM
MOVEI B,37
BOUT
POP P,SCRJFN
MOVEI A,400000
EIR
POPJ P,]
MOVEI A,400000
EIR
MOVSI A,460003
PUSHJ P,.GTJFN
ERROR [ASCIZ /File not available./]
MOVE B,[XWD 70000,100000]
OPENF
JRST [ MOVE A,IJFN
PUSHJ P,CLRJFN
SETZM IJFN
ERROR [ASCIZ /Cannot open file./]]
MOVEI A,400000
DIR
MOVEI B,0
EXCH B,IJFN
MOVEM B,SCRJFN
EIR
POPJ P,
; Get uniform time in secs
UGTAD: GTAD
HRRZS B,A
HLRZS A
IMULI A,=24*=60*=60
ADDB A,B
POPJ P,
; Update script file
SCRUPD: SKIPN SCRJFN
POPJ P,
PUSH P,A
PUSH P,B
SKIPGE SCRTIM
JRST SCRUP0 ; Forced update
PUSHJ P,UGTAD
SUB B,SCRTIM ; Ho long since last update?
CAIG B,=30
JRST SCRUPX ; Never less than 30 secs
CAIL B,=300
JRST SCRUP0 ; Always every 5 min
MOVE A,SCRJFN
RFPTR
SETZ B,
SUB B,SCRCNT
CAIG B,=1000
JRST SCRUPX ; Then not fewer thant 1000 chars
SCRUP0: PUSHJ P,UGTAD
MOVEM B,SCRTIM
MOVE A,SCRJFN
RFPTR
SETZ B,
MOVEM B,SCRCNT
HRLI A,400000
CLOSF
JFCL
HRRZS A
MOVE B,[XWD 70000,20000]
OPENF
JRST 4,.-1
SCRUPX: POP P,B
POP P,A
POPJ P,
; Divert output to a file
SETDIV: MOVEI A,400000
DIR
MOVEI A,0
EXCH A,DIVJFN
SKIPLE A
PUSHJ P,CLRJFN
MOVEI A,400000
EIR
JUMPGE NOA,CPOPJ
MOVSI A,460003
PUSHJ P,.GTJFN
ERROR [ASCIZ /File not found./]
MOVE B,[XWD 70000,100000]
OPENF
JRST [ MOVE A,IJFN
PUSHJ P,CLRJFN
SETZM IJFN
ERROR [ASCIZ /Cannot open./]]
MOVEI A,400000
DIR
MOVEI B,0
EXCH B,IJFN
MOVEM B,DIVJFN
EIR
POPJ P,
; Print where we are
.WHERE: MOVEI A,37
PUSHJ P,.PBOUT
SKIPN SNDJFN(CNX)
JRST NOCC
HRROI A,[ASCIZ /Connection /]
PUSHJ P,.PSOUT
MOVE A,CNX
IMULI A,3
ADDI A,CONNAM
HRROS A
PUSHJ P,.PSOUT
HRROI A,[ASCIZ / from /]
PUSHJ P,.PSOUT
MOVEI A,101
MOVE B,SNDJFN(CNX)
MOVSI C,(<BYTE (3)0,0,1>)
JFNS
SKIPE A,SCRJFN
JFNS
HRROI A,[ASCIZ / to /]
PUSHJ P,.PSOUT
MOVEI A,101
MOVE B,SNDJFN(CNX)
MOVSI 3,(<BYTE (3)0,0,0,1>)
JFNS
SKIPE A,SCRJFN
JFNS
MOVEI A,37
PUSHJ P,.PBOUT
NOCC: MOVE A,[SIXBIT /SYSVER/]
SYSGT
MOVE D,P
HRRZ C,B
HLLZS B
.WHRL: MOVE A,C
HRL A,B
GETAB
JFCL
PUSH P,A
AOBJN B,.WHRL
PUSH P,[0]
HRROI A,1(D)
PUSHJ P,.PSOUT
MOVE P,D
HRROI A,[ASCIZ /
Job /]
PUSHJ P,.PSOUT
GJINF
PUSH P,1
MOVEI A,101
MOVE B,C
MOVEI C,12
PUSHJ P,.NOUT
JFCL
;falls through
;drops in
HRROI A,[ASCIZ /, terminal /]
PUSHJ P,.PSOUT
MOVE B,D
MOVEI C,10
MOVEI A,101
PUSHJ P,.NOUT
JFCL
HRROI A,[ASCIZ /, user /]
PUSHJ P,.PSOUT
POP P,B
MOVEI A,101
DIRST
JFCL
SKIPLE A,SCRJFN
DIRST
JFCL
HRROI A,[ASCIZ /
TELNET version /]
PUSHJ P,.PSOUT
HRROI A,VERNUM
JRST .PSOUT
; Request monitor to send reset to a host
; Is nop if not wheel
.FLUSH: MOVE TAB,HOSTAB
PUSHJ P,SYMVAL
TLNN A,-1
MOVE C,A
PUSH P,C
MOVEI A,400000
DIR
RPCAP
EXCH C,0(P)
PUSH P,C
TRO C,600000
EPCAP
POP P,A
FLHST
MOVEI A,400000
POP P,C
EPCAP
EIR
POPJ P,
; Reset
.RESET: JRST RSTART
; Logout
.LGOUT: HRROI A,[ASCIZ / [Confirm] /]
PUSHJ P,.PSOUT
PUSHJ P,.PBIN
CAIE A,37
POPJ P,
PUSHJ P,.PBOUT
MOVNI 1,1
LGOUT
HALTF
; Quit, exit back to exec
.QUIT: SETOM SCRTIM
PUSHJ P,SCRUPD ; Update script before leaving
MOVEI A,400000
DIR
HALTF
MOVEI A,-4
FFORK
MOVEI A,400000
EIR
POPJ P,
; Send code and control
SNDDCD: IBP BPTR
PUSHJ P,CVDEC
JRST SNDC
SNDOCD: IBP BPTR
SNDOCT: PUSHJ P,CVOCT
JRST SNDC
SNDHCD: IBP BPTR
SETZ A,
SNDHCL: ILDB B,BPTR
JUMPE B,SNDC
CAIL B,"A"
ADDI B,11
ANDI B,17
ASH A,4
ADD A,B
JRST SNDHCL
SNDCTL: MOVE TAB,LTRTB
PUSHJ P,SYMVAL
ANDI A,37
JRST SNDC
SNDBRK: SKIPA A,[TELBRK]
SNDCD1: PUSHJ P,CVOCT
SNDC: MOVE B,A
SKIPN A,SNDJFN(CNX)
POPJ P,
BOUT
MOVEI B,21
MTOPR
POPJ P,
; Set remote mode
SETREM: SKIPE SNDJFN(CNX)
TRO F,REMOTF
POPJ P,
DEFSKT: SETZM WATFLG
SETOM LODFLG
MOVEI A,1
MOVEM A,FSKT ; Default socket is 1
DEFSK0: MOVE A,TERM
CAIN A,37
POPJ P,
MOVE TAB,SKTTAB
PUSHJ P,SYMVAL ; Look for a possible socket
JRST DEFSK0
; Other routines
.CVHST: MOVE A,C
MOVEM A,FHST
MOVE C,2(B)
MOVEM C,FHSTN
CAME TAB,COMTAB
POPJ P,
MOVE A,FHST
JRST CONNX
; Check if host is up
HSTCHK: PUSH P,A
PUSH P,B
MOVE A,[SIXBIT /IMPHRT/]
SYSGT
PUSH P,B
MOVE A,FHSTN
IDIVI A,=36
HRLM A,0(P)
POP P,A
GETAB
SETZ A,
ROT A,(B)
SKIPGE A
AOS -2(P)
POP P,B
POP P,A
POPJ P,
; Set socket number
.STFSK: SKIPA A,2(B)
OCTFSK: PUSHJ P,CVOCT
MOVEM A,FSKT
POPJ P,
DOCOMT: PUSHJ P,GCH
PUSHJ P,ECHOIT
CAIE A,37
JRST DOCOMT
POPJ P,
CVOCT: SKIPA C,[10]
CVDEC: MOVEI C,=10
MOVE A,BPTR
NIN
SETZ B,
MOVE A,B
POPJ P,
SEND: CIS
MOVE P,[XWD -100,SPDL-1]
MOVE PTR,[POINT 7,LINBUF-1,34]
SEND0: PUSHJ P,.PBIN
ANDI A,177
SKIPE XPARNT(CNX) ; Completely transparent?
JRST [ MOVE B,A ; Yes
MOVE A,SNDJFN(CNX)
BOUT
MOVEI B,21
MTOPR
JRST SEND0]
AOSN QUOTF
JRST SEND02 ; Not special (may be shifted though)
CAMN A,QUOT ; Quote character
JRST [ SETOM QUOTF ; Yes, remember
JRST SEND0]
CAMN A,BRKC ; Break substitute?
JRST [ MOVEI A,TELBRK ; Yes, send break
JRST SEND3]
CAMN A,SYNC ; Synch substitute
JRST [ PUSHJ P,SNDSNC ; Yes, send sync seq
JRST SEND0]
CAMN A,UNSFT ; Now for the shifts...unshift?
JRST [ FOR FL IN (<RAISEF(CNX)>,<LOWERF(CNX)>,UCASCF,LCASCF)<
SETZM FL> ; clear all shift flags
JRST SEND0]
CAME A,LCASC
CAMN A,UCASC
JRST SETCAS
CAME A,LCASL
CAMN A,UCASL
JRST SETCAS
SEND02: CAIG A,136 ; Regular character...needs shift?
CAIGE A,100
JRST SEND1 ; Not upper case
AOSE UCASCF ; Upper case. if no upper case shift
PUSHJ P,SFTDWN ; Then see if down shift wanted
JRST SEND3
SEND1: CAIG A,176
CAIGE A,140
JRST SEND3 ; Not lower case either
AOSE LCASCF ; Lower case. if no down shift
PUSHJ P,SFTUP ; Then shift up if wanted
JRST SEND3
SETCAS: SETZM LCASCF ; Clear character shifts
SETZM UCASCF
CAMN A,LCASC ; If lower case char prefix
JRST [ SETOM LCASCF ; Remember
JRST SEND0]
CAMN A,UCASC ; If upper case char prefix
JRST [ SETOM UCASCF ; Remember
JRST SEND0]
SETZM LOWERF(CNX) ; Clear shift locks
SETZM RAISEF(CNX)
CAMN A,LCASL
JRST [ SETOM LOWERF(CNX)
JRST SEND0]
CAMN A,UCASL
JRST [ SETOM RAISEF(CNX)
JRST SEND0]
; JRST SEND3
SEND3: SKIPN LNBFF(CNX) ; If not line buffering
PUSHJ P,SNDBUF ; Send any stuff already buffered
CAIN A,37
JRST [ MOVEI A,15
PUSHJ P,SNDDO
SETCM A,LFCRF(CNX) ; Get complement of switch
HRRI A,12 ; Line feed
JRST .+1]
PUSHJ P,SNDDO
HRRZS A
CAIE A,12
CAIN A,33
PUSHJ P,SNDBUF
JRST SEND0
SFTDWN: AOSE LCASCF
SKIPE LOWERF(CNX)
TRO A,140
POPJ P,
SFTUP: AOSE UCASCF
SKIPE RAISEF(CNX)
TRZ A,40
POPJ P,
SENDO: SKIPA A,CBFCHR
SENDE: MOVE A,ESCAPE
JRST SEND3
SNDBUF: CAMN PTR,[POINT 7,LINBUF-1,34]
POPJ P,
PUSHJ P,TRMST
MOVE PTR,[POINT 7,LINBUF-1,34]
MOVE B,PTR
MOVE A,SNDJFN(CNX)
SETZ C,
SOUT
MOVEI B,21
MTOPR
POPJ P,
SNDDO: SKIPE LNBFF(CNX)
JRST SNDLBF
MOVE B,A
MOVE A,SNDJFN(CNX)
BOUT
PUSH P,B
MOVEI B,21
MTOPR
POP P,B
MOVE A,B
SNDECH: JUMPL A,CPOPJ ; Never echo ch with -1 lh
SKIPN HDX ; If hdx terminal
SKIPN ELCLF(CNX) ; If not local echo
POPJ P, ; Then done
MOVE B,ECHCOC(CNX)
ROT B,(A) ; Prepare to test coc
CAIGE A,40 ; If not control
JUMPGE B,CPOPJ
PUSHJ P,.PEOUT ; Echo
POPJ P,
SNDLBF: CAIE A,"A"-100
CAIN A,"H"-100
JRST [CAMN PTR,[POINT 7,LINBUF-1,34]
JRST [ MOVEI A,7
PUSHJ P,.PBOUT
POPJ P,]
MOVEI A,"\"
PUSHJ P,.PBOUT
LDB A,PTR
PUSHJ P,.PBOUT
MOVE A,PTR
BKJFN
JRST 4,.
MOVEM A,PTR
POPJ P,]
CAIN A,"X"-100
JRST [ MOVEI A,"#"
PUSHJ P,.PBOUT
PUSHJ P,.PBOUT
MOVEI A,37
PUSHJ P,.PBOUT
MOVE PTR,[POINT 7,LINBUF-1,34]
POPJ P,]
CAIN A,"R"-100
JRST [ MOVEI A,37
PUSHJ P,.PBOUT
PUSHJ P,TRMST
MOVE A,[POINT 7,LINBUF-1,34]
PUSHJ P,.PSOUT
POPJ P,]
IDPB A,PTR
SKIPE ELCLF(CNX)
PUSHJ P,SNDECH
POPJ P,
RECV: CIS
MOVE A,RCVJFN(CNX)
MOVEI B,24
MOVSI C,017777
MTOPR ; Ins interrupts on channel 1
MOVE P,[XWD -100,SPDL-1]
SETZM CBFCNT(CNX)
RECVY: SETZM SAVINC(CNX) ; Loop to here to reset buffer
MOVE A,[POINT 7,SAVBUF]
MOVEM A,SAVINP(CNX)
MOVEM A,SAVONP(CNX)
RECV0: SKIPE SAVSWT(CNX) ; Saving output up?
JRST RECVR ; Yes, check if full and do it
SKIPE SAVINC(CNX) ; No, any saved characters?
JRST RECVU ; Yes, unsave them
JRST RECVB0 ; No, get next input
RECVR: MOVEI A,SAVBFS*5-5
CAMG A,SAVINC(CNX)
RECVH: HALTF
RECVB0: MOVE A,RCVJFN(CNX)
RECVB: BIN
CAIL B,200
JRST RCVCTL ; Process telnet control character
SKIPGE CBFCNT(CNX)
JRST RECV0 ; Flushing output
SKIPE SAVSWT(CNX) ; Saving up the output?
JRST RECVS ; Yes, go put it in buffer
RECV1: SKIPE CLROBF
JRST RECVFL
SKIPLE A,DIVJFN
JRST RECVX
MOVE A,B
PUSHJ P,.PEOUT
JRST RECV0
RECVU: SKIPE CLROBF ; Clear output buffer?
JRST [ MOVE A,SAVINP(CNX)
MOVEM A,SAVONP(CNX)
SETZM SAVINC(CNX)
LDB B,SAVONP(CNX)
JRST RECVFL]
MOVNI A,SAVBFS ; No
ADD A,SAVONP(CNX) ; Wrapped pointer if needed
CAMN A,[POINT 7,SAVBUF-1,34]
MOVEM A,SAVONP(CNX) ; Wrap pointer
ILDB B,SAVONP(CNX) ; Get byte
SOS SAVINC(CNX) ; Account
JRST RECV1 ; Go put it out
RECVS: MOVNI A,SAVBFS ; Prepare wrapped pointer
ADD A,SAVINP(CNX)
CAMN A,[POINT 7,SAVBUF-1,34]
MOVEM A,SAVINP(CNX) ; And use it if needed
IDPB B,SAVINP(CNX) ; Store character
AOS A,SAVINC(CNX) ; Account
SKIPE SWOFLG ; Swo and
CAIE A,1 ; First character?
JRST RECV0 ; No
MOVEI A,101
DOBE
HRROI A,[ASCIZ /
Output waiting from connection /]
PUSHJ P,.PSOUT
MOVE A,CNX
IMULI A,3
HRROI A,CONNAM(A)
PUSHJ P,.PSOUT
MOVEI A,37
PUSHJ P,.PBOUT
JRST RECV0
RECVX: BOUT
SKIPE DIVSWT
JRST RECVN
SKIPLE A,SCRJFN
BOUT
MOVE A,B
PUSHJ P,.PEOUT
RECVN: CAIE B,12
JRST RECV0
MOVEI A,101
SOBE
JRST [ HRROI A,[ASCIZ /...
/]
SKIPN DIVSWT
PUSHJ P,.PSOUT
SETOM DIVSWT
JRST RECV0]
SETZM DIVSWT
JRST RECV0
RECVFL: MOVEM B,D
MOVE A,RCVJFN(CNX)
SKIPN SAVINC(CNX)
SIBE
JRST RECV0
MOVEI C,2
RECVF1: MOVEI A,=500
DISMS
MOVE A,RCVJFN(CNX)
SIBE
JRST RECV0
SOJG C,RECVF1
SETZM CLROBF
MOVEI A,37
PUSHJ P,.PBOUT
MOVE B,D
JRST RECV1
IOERR: HRROI A,[ASCIZ /
IO error for connection /]
JRST GENABN
RCVEOF: MOVE A,[XWD 10000,RECVH]
MOVEM A,FKRET2
SKIPN SAVSWT(CNX)
SKIPE SAVINC(CNX)
DEBRK ; Delay eof response until buffer gone
HRROI A,[ASCIZ /Remote disconnect of /]
GENABN: PUSH P,A
AOSE ABNLCK ; Wait for abnormal interrupt handler
JRST [ MOVEI A,=1000
DISMS
JRST .-1]
POP P,A
PUSHJ P,.PSOUT
MOVE A,CNX
IMULI A,3
HRROI A,CONNAM(A)
PUSHJ P,.PSOUT
MOVEM CNX,ABNCNX
MOVEI A,-1
MOVSI B,(1⊗<43-ABNCHN>)
IIC ; Initiate abnormal interrupt in superior
MOVEI A,=100000
DISMS ; And hang
JRST .-2
RCVCTL: CAIN B,TELASC
JRST RECV0 ; Ignore telasc
CAIGE B,205
JRST RCTLDT-200(B)
HRROI A,[ASCIZ /Undefined telnet control /]
PUSHJ P,.PSOUT
MOVEI A,101
MOVEI C,10
PUSHJ P,.NOUT
JFCL
JRST RECV0
RCTLDT: JRST $CFOBF
JRST PRBRK
JRST RECV0
JRST ECHOFF
JRST ECHON
$CFOBF: MOVEI A,1
EXCH A,CBFCNT(CNX) ; Set to 1
JUMPE A,CFOBF0 ; This came first, clear output
SETZM CBFCNT(CNX) ; Came second, clear
JUMPL A,RECV0 ; Jump if not out of phase
MOVEI A,=5000
DISMS ; Wait for any possible ins
SETZM CBFCNT(CNX) ; And cancel it's remainder
JRST RECV0
CFOBF0: MOVEI A,101
SKIPN SAVSWT(CNX)
CFOBF
JRST RECVY
RCVINS: PUSH P,A
SKIPLE CBFCNT(CNX)
JRST [ SETZM CBFCNT(CNX)
JRST RCVINX]
SETOM CBFCNT(CNX)
MOVEI A,101
SKIPN SAVSWT(CNX)
CFOBF
SETZM SAVINC(CNX)
MOVE A,[POINT 7,SAVBUF]
MOVEM A,SAVINP(CNX)
MOVEM A,SAVONP(CNX)
HRRZ A,FKRET2
CAIE A,RECVH
CAIN A,RECVH+1
JRST [MOVEI A,RECV0
HRRM A,FKRET2
JRST RCVINX]
RCVINX: POP P,A
DEBRK
PRBRK: SKIPLE A,BRKC
JRST [ PUSHJ P,.PBOUT
JRST RECV0]
HRROI A,[ASCIZ /'break'/]
PUSHJ P,.PSOUT
JRST RECV0
ECHOFF: SKIPE HDX
JRST [ MOVEI B,TELNEC
MOVE A,SNDJFN(CNX)
BOUT ; Tell him he can't
MOVEI B,21
MTOPR
JRST RECV0]
TDZA A,A
ECHON: SETO A,
MOVEM A,ELCLF(CNX)
JRST RECV0
USE VARPC
VARS: VAR
FMODSW: BLOCK 7
SPARE: BLOCK 3
NMODSW←←.-FMODSW
EVARS: USE
END START